//
//  KAutoLevels.m
//  Kia
//
//  Created by Andrey on 06/05/2009.
//  Copyright 2009 Karma Software. All rights reserved.
//

#import "KAutoLevels.h"
#import "KImage.h"
#import "KImageLayer.h"
#import "KPixel.h"
#import "KHistogram.h"

@implementation KAutoLevels

- (void) computeLevels: (KImage*)image
{
	CGFloat rejectionThresholdForShadows = 
	GetParameterFloatValue(@"RejectionThresholdForShadows");
	CGFloat rejectionThresholdForHighlights = 
	GetParameterFloatValue(@"RejectionThresholdForHighlights");
	enum KImageChannel affectedChannel = 
	GetParameterUIntValue(@"AffectedChannel");
	
	KHistogram* histogram = image.histogram;
	NSUInteger* channelHistogramData = 
	histogram.channelHistograms[affectedChannel].data;	
	NSUInteger imagePixelCount = image.width * image.height;
	
	NSUInteger rejectedPixelCount = 0;
	NSUInteger blackLevelInterval = 0;
	while ((CGFloat)rejectedPixelCount / imagePixelCount < rejectionThresholdForShadows) 
	{
		rejectedPixelCount += channelHistogramData[blackLevelInterval];
		blackLevelInterval++;
	}	
	
	rejectedPixelCount = 0;
	NSUInteger whiteLevelInterval = histogram.intervalCount - 1;
	while ((CGFloat)rejectedPixelCount / imagePixelCount < rejectionThresholdForHighlights) 
	{
		rejectedPixelCount += channelHistogramData[whiteLevelInterval];
		whiteLevelInterval--;
	}
	
	blackLevel = (CGFloat)blackLevelInterval / histogram.intervalCount;
	whiteLevel = (CGFloat)whiteLevelInterval / histogram.intervalCount;
}

- (KPixel*) processPixel: (KPixel*)pixel ofImage: (KImage*)image atX: (NSUInteger)x y: (NSUInteger)y
{
	enum KImageChannel affectedChannel = 
	GetParameterUIntValue(@"AffectedChannel");
	
	if (image != currentImage)
	{
		currentImage = image;
		[self computeLevels: image];
	}
	
	CGFloat channelSpan = whiteLevel - blackLevel;
	CGFloat channelValue = [pixel redundantColorVector].data[affectedChannel];
	
	[pixel setValue:(channelValue - blackLevel) / channelSpan 
		 forChannel:BrightnessImageChannel];
	
	return pixel;
}

- (KImage*) processImage: (KImage*)image inPlace: (Boolean)inPlace
{
	enum KImageChannel affectedChannel = 
	GetParameterUIntValue(@"AffectedChannel");
	
	[self computeLevels: image];
	CGFloat channelSpan = whiteLevel - blackLevel;
	
	ForEachImagePixel(image)
	{
		KPixel* currentPixel = [image pixelAtX:x y:y];
		CGFloat channelValue = [currentPixel redundantColorVector].data[affectedChannel];
		
		[currentPixel setValue:(channelValue - blackLevel) / channelSpan 
					forChannel:BrightnessImageChannel];
	}
	
	[self reset];
	
	return image;
}

- (NSString*) name
{
	return @"Auto Levels";
}

- (void) dealloc
{
	[super dealloc];
}

@end
